abcjs(JavaScript for rendering abc music notation)
ABC notationのJavaScript実装abcjsについて
This library makes it easy to incorporate sheet music into your websites. You can also turn visible ABC text into sheet music on websites that you don't own using a greasemonkey script, or change your own website that contains ABC text with no other changes than the addition of one javascript file. You can also generate MIDI files or play them directly in your browser.
おおまかな流れとか
abcjs ピックアップ
知りたい・参考にしたいこと
音符の、一連の文字列をどう分解して各要素elementsに分けてるのか
abc_tokenizer.jsのtokenizeで、token(一区切りの文字列)に分解して、属性を与える
This is a series of functions that get a particular element out of the passed stream. The return is the number of characters consumed, so 0 means that the element wasn't found. Also returned is the element found. This may be a different length because spaces may be consumed that aren't part of the string.
The return structure for most calls is { len: num_chars_consumed, token: str }
This returns all the tokens inside the passed string. A token is a punctuation mark, a string of digits, a string of letters. Quoted strings are one token. If there is a minus sign next to a number, then it is included in the number. If there is a period immediately after a number, with a number immediately following, then a float is returned. The type of token is returned: quote, alpha, number, punct. If alphaUntilWhiteSpace is true, then the behavior of the alpha token changes.
小節線・繰り返し記号は、『]』、『:』、『[』、『|』、が現れたら、後ろの文字も見ていって(最大5文字)switch-caseで解釈していく。bar_thick_thin, bar_invisible, bar_dbl_repeatとかいろいろ。
音符の長さ指定durationをどう解釈してるか
abc_tokenizer.jsのgetFractionで、fraction(長さ指定は基本的に分数ね)を解釈
code:abc_tokenizer.jp
this.getFraction = function(line, index) {
var num = 1;
var den = 1;
if (line.charAt(index) !== '/') {
var ret = this.getNumber(line, index);
num = ret.num;
index = ret.index;
}
if (line.charAt(index) === '/') {
index++;
if (line.charAt(index) === '/') {
var div = 0.5;
while (line.charAt(index++) === '/')
div = div /2;
return {value: num * div, index: index-1};
} else {
var iSave = index;
var ret2 = this.getNumber(line, index);
if (ret2.num === 0 && iSave === index) // If we didn't use any characters, it is an implied 2
ret2.num = 2;
if (ret2.num !== 0)
den = ret2.num;
index = ret2.index;
}
}
return {value: num/den, index: index};
};
小節線・繰り返し指定を演奏データにどう反映させてるのか
abc_midi_sequencer.jsで、配列voicesに要素elem(配列voiceの各要素)を解釈しつつ入れていく
barを3タイプ(startRepeat, endRepeat, startEnding)に分け、それぞれ解釈
startEndingってなんなんだろう。。。
code:abc_midi_sequencer.js
case "bar":
if (noteEventsInBar > 0) // don't add two bars in a row.
voicesvoiceNumber.push({ el_type: 'bar' }); // We need the bar marking to reset the accidentals.
noteEventsInBar = 0;
// figure out repeats and endings --
// The important part is where there is a start repeat, and end repeat, or a first ending.
var endRepeat = (elem.type === "bar_right_repeat" || elem.type === "bar_dbl_repeat");
var startEnding = (elem.startEnding === '1');
var startRepeat = (elem.type === "bar_left_repeat" || elem.type === "bar_dbl_repeat" || elem.type === "bar_right_repeat");
if (endRepeat) {
var s = startRepeatPlaceholdervoiceNumber;
if (!s) s = 0; // If there wasn't a left repeat, then we repeat from the beginning.
var e = skipEndingPlaceholdervoiceNumber;
if (!e) e = voicesvoiceNumber.length; // If there wasn't a first ending marker, then we copy everything.
voicesvoiceNumber = voicesvoiceNumber.concat(voicesvoiceNumber.slice(s, e));
// reset these in case there is a second repeat later on.
skipEndingPlaceholdervoiceNumber = undefined;
startRepeatPlaceholdervoiceNumber = undefined;
}
if (startEnding)
skipEndingPlaceholdervoiceNumber = voicesvoiceNumber.length;
if (startRepeat)
startRepeatPlaceholdervoiceNumber = voicesvoiceNumber.length;
break;